import os
import uuid

from django.core.exceptions import ObjectDoesNotExist
from django.core.files.storage import default_storage
from django.db import transaction
from rest_framework.parsers import MultiPartParser, FormParser, JSONParser
from rest_framework.views import APIView
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi

from .models import Canvas
from .serializers import CanvasSerializer, CreateCanvasSerializer, UpdateCanvasSerializer, BulkCreateCanvasSerializer
from ..utils.response_utils import api_response, ResponseCode


class ListCanvasView(APIView):
    """
    画布列表接口
    """

    @swagger_auto_schema(
        operation_description="获取画布列表，可根据项目ID过滤",
        manual_parameters=[
            openapi.Parameter('project_id', openapi.IN_QUERY, type=openapi.TYPE_STRING, description="项目ID，选填")
        ],
        responses={
            200: CanvasSerializer,
            500: openapi.Response(description="服务器错误"),
        },
        tags=["画布管理"]
    )
    def get(self, request):
        try:
            project_id = request.query_params.get('project_id')
            if project_id:
                queryset = Canvas.objects.filter(project_id=project_id).order_by('-created_at')
            else:
                queryset = Canvas.objects.all().order_by('-created_at')
            serializer = CanvasSerializer(queryset, many=True)
            return api_response(ResponseCode.SUCCESS, "获取成功", serializer.data)
        except Exception as e:
            return api_response(ResponseCode.INTERNAL_SERVER_ERROR, str(e))


class CreateCanvasView(APIView):
    """
    创建画布接口
    """
    parser_classes = [JSONParser]

    @swagger_auto_schema(
        operation_description="创建新画布",
        request_body=BulkCreateCanvasSerializer(many=True),
        responses={
            200: CanvasSerializer(many=True),
            400: openapi.Response(description="参数错误"),
        },
        tags=["画布管理"]
    )
    def post(self, request):
        try:
            # 启用事务
            with transaction.atomic():
                serializer = BulkCreateCanvasSerializer(data=request.data, many=True, context={'request': request})

                if not serializer.is_valid():
                    return api_response(ResponseCode.BAD_REQUEST, f"参数校验失败：{serializer.errors}",
                                        {"errors": serializer.errors})

                # 批量创建
                instances = serializer.save()

                # 返回完整序列化数据
                result_serializer = CanvasSerializer(instances, many=True)
                return api_response(ResponseCode.SUCCESS, f"成功创建 {len(instances)} 个画布", result_serializer.data)

        except Exception as e:
            return api_response(ResponseCode.INTERNAL_SERVER_ERROR, f"服务器错误: {str(e)}")


class CanvasDetailView(APIView):
    """
    画布详情接口
    """

    @swagger_auto_schema(
        operation_description="获取画布详情",
        manual_parameters=[
            openapi.Parameter('canvas_id', openapi.IN_PATH, type=openapi.TYPE_STRING, description="画布ID")
        ],
        responses={
            200: CanvasSerializer,
            404: openapi.Response(description="画布不存在"),
            500: openapi.Response(description="服务器错误"),
        },
        tags=["画布管理"]
    )
    def get(self, request, canvas_id):
        try:
            canvas = Canvas.objects.get(id=canvas_id)
            serializer = CanvasSerializer(canvas)
            return api_response(ResponseCode.SUCCESS, "获取成功", serializer.data)
        except ObjectDoesNotExist:
            return api_response(ResponseCode.NOT_FOUND, "画布不存在")
        except Exception as e:
            return api_response(ResponseCode.INTERNAL_SERVER_ERROR, str(e))


class UpdateCanvasView(APIView):
    """
    更新画布接口
    """
    parser_classes = [MultiPartParser, FormParser]  # 支持文件上传

    @swagger_auto_schema(
        operation_description="更新画布信息",
        request_body=UpdateCanvasSerializer,
        manual_parameters=[
            openapi.Parameter('canvas_id', openapi.IN_PATH, type=openapi.TYPE_STRING, description="画布ID"),
            openapi.Parameter(
                name='background_image',
                in_=openapi.IN_FORM,
                type=openapi.TYPE_FILE,
                description='上传背景图片（支持JPEG/PNG，最大10MB）',
                required=False
            )
        ],
        consumes=["multipart/form-data", "application/json"],
        responses={
            200: CanvasSerializer,
            400: openapi.Response(description="参数错误"),
            404: openapi.Response(description="画布不存在"),
        },
        tags=["画布管理"]
    )
    def put(self, request, canvas_id):
        try:
            canvas = Canvas.objects.get(id=canvas_id)
            uploaded_file = request.FILES.get('background_image')  # 获取上传文件

            # 处理背景图片上传
            if uploaded_file:
                # 验证文件类型
                allowed_types = ['image/jpeg', 'image/png', 'image/jpg']
                if uploaded_file.content_type not in allowed_types:
                    return api_response(ResponseCode.BAD_REQUEST, "仅支持JPEG/PNG格式")

                # 验证文件大小（10MB限制）
                if uploaded_file.size > 10 * 1024 * 1024:
                    return api_response(ResponseCode.BAD_REQUEST, "文件大小超过10MB")

                # 删除旧文件（保留默认背景图）
                if canvas.background_image:
                    default_storage.delete(canvas.background_image)

                # 生成唯一文件名并保存
                file_ext = os.path.splitext(uploaded_file.name)[1]
                new_filename = f"canvas_bg/{canvas.project.name}/{canvas.name}/{uuid.uuid4()}{file_ext}"
                file_path = default_storage.save(new_filename, uploaded_file)
                canvas.background_image = file_path

            # 处理其他字段更新
            serializer = UpdateCanvasSerializer(canvas, data=request.data)
            if serializer.is_valid():
                new_canvas = serializer.save()
                full_serializer = CanvasSerializer(new_canvas)
                return api_response(ResponseCode.SUCCESS, "更新成功", full_serializer.data)
            return api_response(ResponseCode.BAD_REQUEST, f"参数错误：{serializer.errors}")
        except ObjectDoesNotExist:
            return api_response(ResponseCode.NOT_FOUND, "画布不存在")
        except Exception as e:
            return api_response(ResponseCode.INTERNAL_SERVER_ERROR, f"服务器错误: {str(e)}")


class DeleteCanvasView(APIView):
    """
    删除画布接口
    """

    @swagger_auto_schema(
        operation_description="删除画布",
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            required=['canvas_ids'],
            properties={
                'canvas_ids': openapi.Schema(
                    type=openapi.TYPE_ARRAY,
                    items=openapi.Schema(type=openapi.TYPE_STRING),
                    description="画布ID列表"
                ),
            }
        ),
        responses={
            200: openapi.Response(description="删除成功"),
            404: openapi.Response(description="部分画布不存在"),
        },
        tags=["画布管理"]
    )
    def delete(self, request):
        canvas_ids = request.data.get('canvas_ids', [])
        if not canvas_ids or not isinstance(canvas_ids, list):
            return api_response(ResponseCode.BAD_REQUEST, "参数错误")
        not_found_ids = []
        for canvas_id in canvas_ids:
            try:
                canvas = Canvas.objects.get(id=canvas_id)
                project = canvas.project
                canvas_list = Canvas.objects.filter(project=project).order_by('-created_at')
                if len(canvas_list) <= 1:
                    return api_response(ResponseCode.BAD_REQUEST, "至少保留一个画布")
                # 删除背景图片文件
                if canvas.background_image:
                    background_path = canvas.background_image
                    if default_storage.exists(background_path):
                        default_storage.delete(background_path)
                #TODO: 同时删除对应文件夹
                canvas.delete()
            except ObjectDoesNotExist:
                not_found_ids.append(canvas_id)
        if not_found_ids:
            return api_response(
                ResponseCode.NOT_FOUND,
                f"成功删除画布: {len(canvas_ids) - len(not_found_ids)}个，未找到画布ID: {', '.join(not_found_ids)}"
            )
        return api_response(ResponseCode.SUCCESS, "删除成功")
